<?php


namespace Aitels\Design;

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Schema;


/**
 * 根据定义创建表
 *
 * Class TableBuilder
 * @package Aitels\Design
 */
class TableBuilder
{
    public function build($table, $definition)
    {
        Schema::create($table, function (Blueprint $table) use ($definition) {
            $tablePrimary = null;//表主键
            $tableIndexes = [];//表索引
            $tableUniques = [];//表唯一索引
            foreach ($definition['columns'] as $column) {
                $name = $column['name'];
                $type = $column['type'];
                $param1 = $column['param1'];
                $param2 = $column['param2'];
                $primary = $column['primary'];
                $index = $column['index'];
                $default = $column['default'];
                $comment = $column['comment'];
                $columnBuilder = $this->buildColumn($table, $name, $type, $param1, $param2);
                if (!is_null($default))
                    $columnBuilder->default($default);

                if (!is_null($comment))
                    $columnBuilder->comment($comment);

                if (isset($column['nullable']))
                    $columnBuilder->nullable();

                if ($primaryDefinition = $this->parsePrimaryDefinition($name, $primary))
                    $tablePrimary = $primaryDefinition;

                list($indexDefinition, $uniqueDefinition) = $this->parseIndexDefinition($name, $index);

                if ($indexDefinition)
                    $tableIndexes[] = $indexDefinition;

                if ($uniqueDefinition)
                    $tableUniques[] = $uniqueDefinition;
            }
            $this->addConstraints($table, $tablePrimary, $tableIndexes, $tableUniques);
        });
        echo "build $table .\n";
    }


    public function buildColumn(Blueprint $table, $name, $type, $param1, $param2)
    {

        $builder = null;
        switch (true) {
            case is_null($param1) && is_null($param2):
                $builder = $table->{$type}($name);
                break;
            case !is_null($param1) && is_null($param2):
                $builder = $table->{$type}($name, $param1);
                break;
            case !is_null($param1) && !is_null($param2):
                $builder = $table->{$type}($name, $param1, $param2);
                break;
        }

        return $builder;
    }

    public function parsePrimaryDefinition($name, $primary)
    {
        if (!is_null($primary)) {
            if (Str::contains($primary, ',')) {
                $primary = explode(',', $primary);
            } else {
                $primary = $name;
            }
            return $primary;
        }
        return null;

    }

    public function parseIndexDefinition($name, $index)
    {
        $indexDefinition = null;
        $uniqueDefinition = null;
        if (!is_null($index)) {
            if ($index === 'index') {
                //普通索引
                $indexDefinition = $name;
            } else if ($index === 'unique') {
                //唯一索引
                $uniqueDefinition = $name;
            } else if (Str::contains($index, 'index:')) {
                //联合索引  [index:name,email,phone]
                $indexDefinition = explode(',', Str::after($index, ':'));
            } else if (Str::contains($index, 'unique:')) {
                //联合唯一索引  [unique:name,email,phone]
                $uniqueDefinition = explode(',', Str::after($index, ':'));
            }
            return [$indexDefinition, $uniqueDefinition];
        }
        return [null, null];
    }


    public function addConstraints(Blueprint $table, $tablePrimary, $tableIndexes, $tableUniques)
    {

        if ($tablePrimary) {
            $table->primary($tablePrimary);
        }
        if ($tableIndexes) {
            foreach ($tableIndexes as $tableIndex) {
                $table->index($tableIndex);
            }
        }
        if ($tableUniques) {
            foreach ($tableUniques as $tableUnique) {
                $table->unique($tableUnique);
            }
        }
    }

}